package com.jichangxiu.system.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.jichangxiu.common.annotation.Scope;
import com.jichangxiu.common.entity.bo.CompareResult;
import com.jichangxiu.common.exception.ServiceException;
import com.jichangxiu.common.utils.ConvertUtils;
import com.jichangxiu.framework.service.impl.BaseServiceImpl;
import com.jichangxiu.framework.utils.CompareUtils;
import com.jichangxiu.system.entity.bo.SysMenuBo;
import com.jichangxiu.system.entity.bo.SysPowerBo;
import com.jichangxiu.system.entity.dto.query.QuerySysPower;
import com.jichangxiu.system.entity.po.SysMenu;
import com.jichangxiu.system.entity.po.SysPower;
import com.jichangxiu.system.entity.vo.SysPowerVo;
import com.jichangxiu.system.mapper.SysPowerMapper;
import com.jichangxiu.system.service.SysPowerService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * SysPowerServiceImpl:
 *
 * @author JiChangXiu
 * @create 2024-06-28 13:44:36
 */
@Service
public class SysPowerServiceImpl extends BaseServiceImpl<SysPowerMapper, SysPower, SysPowerVo> implements SysPowerService {

    /**
     * 增加 / 修改 / 删除 系统权限列表
     *
     * @param sysMenuBo      系统菜单
     * @param sysPowerBoList 系统权限对象列表
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addOrDelOrEdit(SysMenuBo sysMenuBo, List<SysPowerBo> sysPowerBoList) {
        if (ObjectUtil.isEmpty(sysMenuBo) || StrUtil.isEmpty(sysMenuBo.getId()))
            throw new ServiceException("菜单不能为空");
        // 做一个基础校验
        sysPowerBoList.forEach(sysPowerBo -> {
            if (StrUtil.isEmpty(sysPowerBo.getCode()))
                throw new ServiceException("权限标识不能为空");
            if (StrUtil.isEmpty(sysPowerBo.getAction()))
                throw new ServiceException("路径不能为空");
            if (sysPowerBoList.stream().filter(bo -> bo.getCode().equals(sysPowerBo.getCode())).count() > 1)
                throw new ServiceException("权限标识不能重复");
        });
        // 数据库中保存的本次修改之前的数据
        List<SysPower> dbSysPowerList = list(new LambdaQueryWrapper<SysPower>().in(SysPower::getMenuId, sysMenuBo.getId()));
        List<SysPowerBo> dbSysPoserBoList = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(dbSysPowerList))
            dbSysPoserBoList = ConvertUtils.convert(dbSysPowerList, SysPowerBo.class);
        CompareResult<SysPowerBo> compareResult = CompareUtils.compareList(sysPowerBoList, dbSysPoserBoList, SysPowerBo::getCode);
        // 本次要新增的
        List<SysPower> addSysMenuPowerList = ConvertUtils.convert(compareResult.getAddList(), SysPower.class);
        // 本次要修改的
        List<SysPower> editSysMenuPowerList = ConvertUtils.convert(compareResult.getEditList(), SysPower.class);
        // 本次要删除的
        List<SysPower> deleteSysMenuPowerList = ConvertUtils.convert(compareResult.getDeleteList(), SysPower.class);
        boolean b1 = true;
        if (ObjectUtil.isNotEmpty(addSysMenuPowerList))
            b1 = saveBatch(addSysMenuPowerList);
        boolean b2 = true;
        if (ObjectUtil.isNotEmpty(editSysMenuPowerList))
            b2 = updateBatchById(editSysMenuPowerList);
        boolean b3 = true;
        if (ObjectUtil.isNotEmpty(deleteSysMenuPowerList))
            b3 = removeBatchByIds(deleteSysMenuPowerList.stream().map(SysPower::getId).collect(Collectors.toList()));
        return b1 && b2 && b3;
    }

    /**
     * 根据主键查询系统权限
     *
     * @param id       系统权限主键
     * @param isExtend 是否扩展
     * @return 系统权限详情
     */
    @Override
    public SysPowerVo info(@NotBlank(message = "主键不能为空") String id, Boolean isExtend) {
        SysPowerVo sysPowerVo = getBaseMapper().selectJoinOne(SysPowerVo.class, buildQueryWrapper(QuerySysPower.builder().id(id).build()));
        if (Boolean.TRUE.equals(isExtend)) {
            if (ObjectUtil.isNotEmpty(sysPowerVo))
                sysPowerVo = renderSysPowerVoList(ListUtil.toList(sysPowerVo)).get(0);
        }
        return sysPowerVo;
    }

    /**
     * （可分页）查询系统权限列表
     *
     * @param querySysPower 查询视图对象
     * @return （分页）系统权限列表
     */
    @Override
    public Page<SysPowerVo> lists(QuerySysPower querySysPower) {
        Page<SysPowerVo> sysPowerVoPage = getBaseMapper().selectJoinPage(startPage(), SysPowerVo.class, buildQueryWrapper(querySysPower));
        if (Boolean.TRUE.equals(querySysPower.getIsExtend()))
            sysPowerVoPage.setRecords(renderSysPowerVoList(sysPowerVoPage.getRecords()));
        return sysPowerVoPage;
    }

    /**
     * 根据租户ID和用户ID查询系统权限列表
     *
     * @param menuIdList 菜单ID列表
     * @return 系统权限列表
     */
    @Override
    public List<SysPowerVo> listsByMenuIdList(List<String> menuIdList) {
        return getBaseMapper().listsByMenuIdList(menuIdList);
    }

    /**
     * 渲染视图
     *
     * @param sysPowerVoList 视图列表
     * @return 渲染后的视图列表
     */
    private List<SysPowerVo> renderSysPowerVoList(List<SysPowerVo> sysPowerVoList) {
        if (ObjectUtil.isNotEmpty(sysPowerVoList)) {
            // todo 扩展信息填入
        }
        return sysPowerVoList;
    }

    /**
     * 构建查询条件
     *
     * @param querySysPower 查询用业务对象
     * @return 查询条件
     */
    private MPJLambdaWrapper<SysPower> buildQueryWrapper(QuerySysPower querySysPower) {
        MPJLambdaWrapper<SysPower> lambdaQueryWrapper = new MPJLambdaWrapper<SysPower>()
                .selectAll(SysPower.class)
                .leftJoin(SysMenu.class, SysMenu::getId, SysPower::getMenuId, ext -> ext
                        .selectAs(SysMenu::getCode, SysPowerVo::getMenuCode)
                        .selectAs(SysMenu::getName, SysPowerVo::getMenuName))
                .disableSubLogicDel();
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(querySysPower.getId()), SysPower::getId, querySysPower.getId());
        lambdaQueryWrapper.like(StrUtil.isNotEmpty(querySysPower.getCode()), SysPower::getCode, querySysPower.getCode());
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(querySysPower.getAction()), SysPower::getAction, querySysPower.getAction());
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(querySysPower.getMenuId()), SysPower::getMenuId, querySysPower.getMenuId());
        lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(querySysPower.getSort()), SysPower::getSort, querySysPower.getSort());
        lambdaQueryWrapper.apply(StrUtil.isNotEmpty(querySysPower.getScope()), querySysPower.getScope());
        return lambdaQueryWrapper;
    }

}